Unit BModelGeneratorUnit;

{$mode objfpc}{$H+}

Interface

Uses
  Classes, SysUtils, BGeneratorUnit, BListsUnit, BCommonUnit, BPeaUnit,
    strutils;

Type

{ BModelGeneratorClass }

 BModelGeneratorClass = Class(BGeneratorClass)
  Private
    Procedure AddPluralSaveProcedure(Const aProperty: BPeaPropertyClass;
      Var aIndex: Integer);
    //** Save Plural Peas
    Procedure SavePluralPeas;
  Public
    //** Update Uses part of PeaUnit
    Procedure UpdateUses;
    //** Update Consts part of PeaUnit
    Procedure UpdateConsts;
    //** Update Properties of PeaUnit
    Procedure UpdateProperties;
    //** Update Initialize part of BPeaClass
    Procedure UpdateInitialize;
    //** Update InitializeObjects part of BPeaClass
    Procedure UpdateInitializeObjects;
    //** Update Load parts for plural Peas Fields of BPeaClass interface
    Procedure UpdateLoadPlurals;
    //** Update Single parts for plural Peas Fields of BPeaClass interface
    Procedure UpdateAddGetRemovePlurals;
    //** Update Save method of BPeaClass
    Procedure UpdateSave;
    //** Update Load method of BPeaClass
    Procedure UpdateLoad;
    //** Update destructor of BPeaClass
    Procedure UpdateBurn;
    //** Update Load method at BPeasManagerClass
    Procedure UpdateManagerLoad;
    //** Update Load of plural Peas Fields at BPeasManagerClass
    Procedure UpdateManagerPluralLoad;

    //**
    Procedure Update; Override;
    //**
    Procedure SavePeaUnit; Override;

    Constructor Build(Const aPeaPath: String; Const aPea: BPeaClass;
      Const aProjectName: String);
End;

Implementation

Uses BModelCodePartsUnit;

ResourceString
  rsModelsDir = 'Models/';
  mskPeaModelUnit = 'b%sunit.pas';
  rsUses = 'Uses';
  rsConst = 'Const';
  mskSQL_NAME = 'SQL_NAME = ''%s'';';
  mskSQL_NAME_MATCH = 'SQL_NAME_MATCH = ''%0:s = :%0:s'';';
  mskSQL_PLURAL_PEA = 'SQL_%0:s = ''%0:s'';';
  mskSQL_HOLDERS_PEA = 'SQL_%0:s = ''%1:s'';';
  mskPeaField = 'b%s: %s;';
  rsPropertiesPriv = 'PropertiesPrivate';
  rsPropertiesPublic = 'PropertiesPublic';
  mskPeaProperty = 'Property %0:s: %1:s Read b%0:s Write b%0:s;';
  rsInitializeDeclare = 'InitializeDeclare';
  mskPeaParam = 'Const a%s: %s';
  mskPeaInitInterface = 'Procedure Initialize%s;';
  mskPeaInitImplementation = 'Procedure B%sClass.Initialize%s;';
  rsInitialize = 'Initialize';
  rsBegin = 'Begin';
  rsInitializeObjects = 'InitializeObjects';
  rsInitializeObjectsCall = 'InitializeObjects;';
  mskPeaFieldSetValue = 'b%0:s := a%0:s;';
  rsValidate = 'Validate;';
  rsEnd = 'End;';
  mskPeaBuilding = 'b%0:s := %1:s.Build;';
  rsCheckPeaNew = 'If ID < 0 Then';
  rsSave = 'Save';
  mskAddParamPea = '.AddParam(SQL_%s)';
  mskTreePeaSQLInsert = 'aSQL.Builder.Insert(SQL_NAME).AddGenerator.AddParam'
    +'(SQL_DELETED).AddParam(SQL_PARENT).AddParam(SQL_PRIOR).AddParam(SQL_NEXT'
    +')%s.Returning(SQL_ID).Executable';
  mskPlainPeaSQLInsert = 'aSQL.Builder.Insert(SQL_NAME).AddGenerator.'
    +'AddParam(SQL_DELETED).AddParam(SQL_PRIOR).AddParam(SQL_NEXT)%s.Returning'
    +'(SQL_ID).Executable';
  rsEndWOSemiColon = 'End';
  rsElse = 'Else';
  mskTreePeaSqlUpdate = 'aSQL.Builder.Update(SQL_NAME).AddParam(SQL_'
    +'DELETED).AddParam(SQL_PARENT).AddParam(SQL_PRIOR).AddParam(SQL_NEXT)%s.'
    +'Where(SQL_ID_MATCH);';
  mskPlainPeaSqlUpdate = 'aSQL.Builder.Update(SQL_NAME).AddParam(SQL_'
    +'DELETED).AddParam(SQL_PRIOR).AddParam(SQL_NEXT)%s.Where(SQL_ID_MATCH);';
  rsAddSqlParamID = 'aSQL.AddParam(SQL_ID, ID);';
  rsAddSqlParamDeleted = 'aSQL.AddParam(SQL_DELETED, bDeleted);';
  rsCheckParentNil = 'If Parent = nil Then';
  rsAddSqlParamParentNil = 'aSQL.AddParam(SQL_PARENT, -1)';
  rsAddSqlParamParentValue = 'aSQL.AddParam(SQL_PARENT, Parent.ID);';
  rsCheckPriorNil = 'If Prior = nil Then';
  rsAddSqlParamPriorNil = 'aSQL.AddParam(SQL_PRIOR, -1)';
  rsAddSqlParamPriorValue = 'aSQL.AddParam(SQL_PRIOR, Prior.ID);';
  rsCheckNextNil = 'If Next = nil Then';
  rsAddSqlParamNextNil = 'aSQL.AddParam(SQL_NEXT, -1)';
  rsAddSqlParamNextValue = 'aSQL.AddParam(SQL_NEXT, Next.ID);';
  rsPostSQL = 'Result := aQuery.Post(aSQL);';
  rsIfResultThen = 'If Result Then';
  rsSetIDIfNewPea = 'If Result And (ID < 0) Then ' +
    'bID := aQuery.ByInteger(SQL_ID);';
  rsLoad = 'Load';
  mskOriginalPeaProperty = ' aObject.%0:s';
  mskPeaInitializeOnLoad = 'Initialize(%s);';
  mskPluralPeaLoadWithLock = '%0:s.Load(aObject.%0:s.LockList);';
  mskPluralUnlockList = 'aObject.%0:s.UnlockList;';
  rsBurn = 'Burn';
  mskPeaBurn = 'b%0:s.Burn;';
  mskHoldersPurge = 'b%0:s.Purge;';
  rsPluralSavesDeclare = 'PluralSavesDeclare';
  rsPluralSaves = 'PluralSaves';
  mskSavePluralCall = 'Result := Result And Save%s(aQuery);';
  mskSavePluralDeclare = 'Function Save%s(Const aQuery: BQueryClass): Boolean;';
  mskSavePlural='Function B%sClass.Save%s(Const aQuery: BQueryClass): Boolean;';
  rsVar = 'Var';
  rsLoadPluralDeclare = 'LoadPluralDeclare';
  rsLoadPlural = 'LoadPlural';
  rsManagerLoad = 'ManagerLoad';
  rsManagerLoadPrepare = 'ManagerLoadPrepare';
  rsManagerLoadPluralCall = 'ManagerLoadPluralCall';
  mskPeaPluralProperiesLoad = 'Procedure Load%0:s(Const a%0:s: %1:s);';
  rsManagerLoadVars = 'ManagerLoadVars';
  mskSetClassID = 'bClassID := %d;';
  mskByString = 'ByString(SQL_%s)';
  mskByInteger = 'ByInteger(SQL_%s)';
  mskByDouble = 'ByDouble(SQL_%s)';
  mskByDateTime = 'ByDateTime(SQL_%s)';
  mskByPea = 'a%1:sManager.GetObject(ByInteger(SQL_%0:s))';
  rsFirst = '%0:s';
  mskByBoolean = 'ByBoolean(SQL_%s)';
  mskManagersDeclare = 'a%0:sManager: B%0:sManagerClass;';
  mskOwnersListDeclare = 'a%0:s: B%0:sOwnersList;';
  rsWithAQueryDo = 'With aQuery Do';
  mskAddObjectWithInitialize = 'AddObject(ByInteger(SQL_ID)).Initialize(%s);';
  mskAddTreeObjectWithInitialize = 'AddObject(ByInteger(SQL_ID), ' +
    'ByInteger(SQL_PARENT), ByInteger(SQL_PRIOR), ByInteger(SQL_NEXT)).' +
    'Initialize(%s);';
  mskBuildManagers = 'a%0:sManager := B%0:sManagerClass.Build;';
  mskBuildOwnersList = 'a%0:s := B%0:sOwnersList.Build;';
  rsLoadPluralsCall = 'Load%s(aQuery);';
  rsLoadHoldersCall = 'Load%0:s(aQuery, a%0:s, SQL_NAME + ''_'' + SQL_%1:s,' +
    'SQL_NAME);';
  rsManagerLoadFinal = 'ManagerLoadFinal';
  mskBurnOwners = 'a%0:s.Burn;';
  mskBurnManagers = 'a%0:sManager.Burn;';
  rsManagerLoadPluralDeclare = 'ManagerLoadPluralDeclare';
  rsManagerLoadPlural = 'ManagerLoadPlural';
  mskManagarPluralLoadDeclare = 'Procedure Load%s(Const aQuery: BQueryClass);';

  {$define ppkPlainPlural :=
    ppkStrings,
    ppkIntegers,
    ppkDoubles,
    ppkDateTimes,
    ppkBooleans
  }

  {$define ppkPlain :=
    ppkString,
    ppkInteger,
    ppkDouble,
    ppkDate,
    ppkDateTime,
    ppkTime,
    ppkBoolean,
    ppkEnum
  }

{ BModelGeneratorClass }

Procedure BModelGeneratorClass.AddPluralSaveProcedure(
  Const aProperty: BPeaPropertyClass; Var aIndex: Integer);
Begin
  If Not(aProperty.IsPlural) Then Raise Exception.Create('Illegall call');
  Case aProperty.Kind Of
    ppkPeas:
      AddLines(CODE_SAVE_PEAS_PLURAL,
        [Pea.Caption, '', aProperty.Pea.PluralCaption, aProperty.PluralCaption,
        aProperty.SQLCaption], aIndex);
    ppkHolders:
      AddLines(CODE_SAVE_HOLDERS_PLURAL,
        [Pea.Caption, '', aProperty.Pea.PluralCaption, aProperty.PluralCaption,
        aProperty.SQLCaption], aIndex);
    Else
      AddLines(CODE_SAVE_PLAIN_PLURAL,
        [Pea.Caption, aProperty.PluralCaption, aProperty.SQLCaption], aIndex);
  End;
End;

Procedure BModelGeneratorClass.SavePluralPeas;
Var
  i: Integer;
  aDeclareIndex, aSaveIndex: Integer;
Begin
  aDeclareIndex := ClearSection(rsPluralSavesDeclare);
  For i := 0 To Pea.Properties.Count - 1 Do
    If Pea[i].IsPlural Then
      AddLine(mskSavePluralDeclare, [Pea[i].PluralCaption], 6, aDeclareIndex);

  aSaveIndex := ClearSection(rsPluralSaves);
  For i := 0 To Pea.Properties.Count - 1 Do
    If Pea[i].IsPlural Then
      AddPluralSaveProcedure(Pea[i], aSaveIndex);
End;

Procedure BModelGeneratorClass.UpdateUses;
Const
  MASK_PEA_UNIT = ', B%sUnit';
Var
  aUses: String = '';
  i, aIndex: Integer;
  aStringList: TStringList;
Begin
  aStringList := TStringList.Create;
  For i := 0 To Pea.Properties.Count - 1 Do
    If (Pea[i].Kind In [ppkPea, ppkPeas, ppkHolders]) And
      (aStringList.IndexOf(Pea[i].Pea.Caption) = -1) Then
      Begin
        aUses += Format(MASK_PEA_UNIT, [Pea[i].Pea.Caption]);
        aStringList.Add(Pea[i].Pea.Caption);

        If Pea[i].Kind = ppkHolders Then
          If aStringList.IndexOf(Pea[i].Pea.HoldingPea.Caption) = -1 Then
            Begin
              aUses += Format(MASK_PEA_UNIT, [Pea[i].Pea.HoldingPea.Caption]);
              aStringList.Add(Pea[i].Pea.HoldingPea.Caption);
            End;
      End;
  aStringList.Free;

  aIndex := ClearSection(rsUses);
  AddLine(aUses, 2, aIndex);
End;

Procedure BModelGeneratorClass.UpdateConsts;
Var
  i, j, aIndex: Integer;
  aBuffer: BStringsList;
  Procedure AddConst(Const aString: String; Const aParams: Array Of Const);
  Begin
    If aBuffer.IndexOf(Format(aString, aParams)) = -1 Then
      aBuffer.Add(Format(aString, aParams));
  End;

Begin
  aBuffer := BStringsList.Build;
  aIndex := ClearSection(rsConst);
  AddLine(mskSQL_NAME_MATCH, [upcase(Pea.Caption)], 2, aIndex);
  AddLine(mskSQL_NAME, [upcase(Pea.Caption)], 2, aIndex);
  For i := 0 To Pea.Properties.Count - 1 Do
    Begin
      If Pea[i].Kind = ppkHolders Then
        For j := 0 To Pea[i].Pea.Properties.Count - 1 Do
          Begin
            AddConst(mskSQL_PLURAL_PEA, [Pea[i].Pea[j].SQLCaption]);
            AddConst(mskSQL_PLURAL_PEA, [UpCase(Pea[i].Pea.HoldingPea.Caption)]);
          End;
      AddConst(mskSQL_PLURAL_PEA, [Pea[i].SQLCaption]);
    End;
  For i := 0 To aBuffer.Count - 1 Do
    AddLine(aBuffer[i], 2, aIndex);
  aBuffer.Burn;
End;

Procedure BModelGeneratorClass.UpdateProperties;
Var
  i, aIndex: Integer;
Begin
  aIndex := ClearSection(rsPropertiesPriv);
  For i := 0 To Pea.Properties.Count - 1 Do
    If Not(Pea[i].IsPlural) Then
      AddLine(mskPeaField, [Pea[i].Caption, Pea[i].KindString], 6, aIndex)
    Else
      AddLine(mskPeaField, [Pea[i].PluralCaption,Pea[i].KindString], 6, aIndex);

  aIndex := ClearSection(rsPropertiesPublic);
  For i := 0 To Pea.Properties.Count - 1 Do
    If Not(Pea[i].IsPlural) Then
      AddLine(mskPeaProperty, [Pea[i].Caption, Pea[i].KindString], 6, aIndex)
    Else
      AddLine(mskPeaProperty,[Pea[i].PluralCaption,Pea[i].KindString],6,aIndex);
End;

Procedure BModelGeneratorClass.UpdateInitialize;
Var
  aIndex: Integer = -1;
  aDeclare: String = '';
  aDeclareProperties: String;
  i: Integer;
Begin
  aIndex := ClearSection(rsInitializeDeclare);
  For i := 0 To Pea.Properties.Count - 1 Do
    If Not(Pea[i].IsPlural) Then
      Begin
        If Not(aDeclareProperties = '') Then aDeclareProperties += ';'+#32;
        aDeclareProperties += Format(mskPeaParam,
          [Pea[i].Caption, Pea[i].KindString]);
      End;
  If Not(aDeclareProperties = '') Then
    aDeclareProperties := '(' + aDeclareProperties + ')';
  AddLine(mskPeaInitInterface, [aDeclareProperties], 6, aIndex);

  aIndex := ClearSection(rsInitialize);
  AddLine(mskPeaInitImplementation,
    [Pea.Caption, aDeclareProperties], 0, aIndex);
  AddLine(rsBegin, 0, aIndex);
  AddLine(rsInitializeObjectsCall, 2, aIndex);
  For i := 0 To Pea.Properties.Count - 1 Do
    If Not(Pea[i].IsPlural) Then
      AddLine(mskPeaFieldSetValue, [Pea[i].Caption], 2, aIndex);
  AddLine(rsValidate, 2, aIndex);
  AddLine(rsEnd, 0, aIndex);
End;

Procedure BModelGeneratorClass.UpdateInitializeObjects;
Var
  i, aIndex: Integer;
Begin
  aIndex := ClearSection(rsInitializeObjects);
  AddLine(mskSetClassID, [Pea.ID], 6, aIndex);
  For i := 0 To Pea.Properties.Count - 1 Do
    If Pea[i].IsPlural Then
      AddLine(mskPeaBuilding,[Pea[i].PluralCaption,Pea[i].KindString],6,aIndex);
End;

Procedure BModelGeneratorClass.UpdateLoadPlurals;
Var
  i, aIndex: Integer;
Begin
  aIndex := ClearSection(rsLoadPluralDeclare);
  For i := 0 To Pea.Properties.Count - 1 Do
    If Pea[i].IsPlural Then
      AddLine(mskPeaPluralProperiesLoad,
        [Pea[i].PluralCaption, Pea[i].KindUnlocked], 6, aIndex);

  aIndex := ClearSection(rsLoadPlural);
  For i := 0 To Pea.Properties.Count - 1 Do
    If Pea[i].IsPlural Then
      Case Pea[i].Kind Of
        ppkHolders:
          AddLines(CODE_LOAD_HOLDERS_PLURAL,
            [Pea.Caption, Pea[i].PluralCaption, Pea[i].KindUnlocked], aIndex);
        Else
          AddLines(CODE_LOAD_PLAIN_PLURAL,
            [Pea.Caption, Pea[i].PluralCaption, Pea[i].KindUnlocked], aIndex);
      End;
End;

Procedure BModelGeneratorClass.UpdateAddGetRemovePlurals;
Begin

End;

Procedure BModelGeneratorClass.UpdateSave;
Var
  i: Integer;
  aIndex: Integer;
  aFields: String = '';
  Procedure SaveTreeBaseParams;
  Begin
    AddLine(rsCheckParentNil, 4, aIndex);
    AddLine(rsAddSqlParamParentNil, 6, aIndex);
    AddLine(rsElse, 4, aIndex);
    AddLine(rsAddSqlParamParentValue, 6, aIndex);
    AddLine(rsCheckPriorNil, 4, aIndex);
    AddLine(rsAddSqlParamPriorNil, 6, aIndex);
    AddLine(rsElse, 4, aIndex);
    AddLine(rsAddSqlParamPriorValue, 6, aIndex);
    AddLine(rsCheckNextNil, 4, aIndex);
    AddLine(rsAddSqlParamNextNil, 6, aIndex);
    AddLine(rsElse, 4, aIndex);
    AddLine(rsAddSqlParamNextValue, 6, aIndex);
  End;

  //TODO: repleace it for real Prior and Next for plain Pea
  Procedure SavePlainBaseParams;
  Begin
    AddLine(rsAddSqlParamPriorNil + ';', 4, aIndex);
    AddLine(rsAddSqlParamNextNil + ';', 4, aIndex);
  End;
Begin
  For i := 0 To Pea.Properties.Count - 1 Do
    If Not(Pea[i].IsPlural) Then
      aFields += Format(mskAddParamPea, [Pea[i].SQLCaption]);

  aIndex := ClearSection(rsSave);
  AddLine(rsCheckPeaNew, 4, aIndex);
  If Pea.Kind = pkTree Then
    AddLine(mskTreePeaSQLInsert, [aFields], 6, aIndex)
  Else
    AddLine(mskPlainPeaSQLInsert, [aFields], 6, aIndex);
  AddLine(rsElse, 4, aIndex);
  AddLine(rsBegin, 6, aIndex);
  If Pea.Kind = pkTree Then
    AddLine(mskTreePeaSqlUpdate, [aFields], 8, aIndex)
  Else
    AddLine(mskPlainPeaSqlUpdate, [aFields], 8, aIndex);
  AddLine(rsAddSqlParamID, 8, aIndex);
  AddLine(rsEnd, 6, aIndex);
  AddLine('', 4, aIndex);

  AddLine(rsAddSqlParamDeleted, 4, aIndex);
  If Pea.Kind = pkTree Then
    SaveTreeBaseParams
  Else
    SavePlainBaseParams;
  For i := 0 To Pea.Properties.Count - 1 Do
    If Not(Pea[i].IsPlural) Then
      If Pea[i].Kind In [ppkPea] Then
        Begin
          AddLine('If Not(%1:s = nil) Then aSQL.AddParam(SQL_%0:s, %1:s.ID)',
            [Pea[i].SQLCaption, Pea[i].Caption], 4, aIndex);
          AddLine('Else aSQL.AddParam(SQL_%s, -1);',
            [Pea[i].SQLCaption], 4, aIndex);
        End
      Else
        AddLine('aSQL.AddParam(SQL_%s, %s);',
          [Pea[i].SQLCaption, Pea[i].Caption], 4, aIndex);

  AddLine(rsPostSQL, 4, aIndex);
  AddLine(rsSetIDIfNewPea, 4, aIndex);
  For i := 0 To Pea.Properties.Count - 1 Do
    If Pea[i].IsPlural Then
      AddLine(mskSavePluralCall, [Pea[i].PluralCaption], 4, aIndex);

  SavePluralPeas;
End;

Procedure BModelGeneratorClass.UpdateLoad;
Var
  i, aIndex: Integer;
  aParams: String = '';
Begin
  aIndex := ClearSection(rsLoad);
  For i := 0 To Pea.Properties.Count - 1 Do
    If Not(Pea[i].IsPlural) Then
      AppendCommaString(aParams, mskOriginalPeaProperty, [Pea[i].Caption]);
  AddLine(mskPeaInitializeOnLoad, [aParams], 2, aIndex);
  For i := 0 To Pea.Properties.Count - 1 Do
    Case Pea[i].Kind Of
      ppkPeas, ppkStrings, ppkIntegers, ppkDoubles, ppkDateTimes, ppkBooleans:
        AddLines(CODE_ORIGINAL_LOAD_PLAIN_PLURAL, [Pea[i].PluralCaption],
          aIndex);
      ppkHolders:
        AddLines(CODE_ORIGINAL_LOAD_HOLDERS_PLURAL, [Pea[i].PluralCaption],
          aIndex);
    End;
End;

Procedure BModelGeneratorClass.UpdateBurn;
Var
  i, aIndex: Integer;
Begin
  aIndex := ClearSection(rsBurn);
  For i := 0 To Pea.Properties.Count - 1 Do
    If Pea[i].IsPlural Then
      Begin
        If Pea[i].Kind In [ppkHolders] Then
          AddLine(mskHoldersPurge, [Pea[i].PluralCaption], 2, aIndex);
        AddLine(mskPeaBurn, [Pea[i].PluralCaption], 2, aIndex);
      End;
End;

Procedure BModelGeneratorClass.UpdateManagerLoad;
Var
  i, aIndex: Integer;
  aManagers, aOwners: BStringsList;
  Procedure CheckBufferState(Const aProperty: BPeaPropertyClass);
  Var
    i: Integer;
    aManager: String = '';
    aOwner: String = '';
  Begin
    Case aProperty.Kind Of
      ppkPea, ppkPeas:
        aManager := aProperty.Pea.PluralCaption;
      ppkHolders:
        Begin
          aOwner := aProperty.Pea.PluralCaption;
          aManager := aProperty.Pea.HoldingPea.PluralCaption;
        End;
    End;
    If Not(aManager='') And (aManagers.IndexOf(aManager) = -1) Then
      aManagers.Add(aManager);
    If Not(aOwner = '') And (aOwners.IndexOf(aOwner) = -1) Then
      aOwners.Add(aOwner);
  End;

  Function GetInitializeParams: String;
  Var
    i: Integer;
    aAppendMask: String;
  Begin
    Result := '';
    For i := 0 To Pea.Properties.Count - 1 Do
      If Not(Pea[i].IsPlural) Then
        Begin
          If Not(Result = '') Then Result += ',' + #32;
          Case Pea[i].Kind Of
            ppkString: aAppendMask := mskByString;
            ppkInteger, ppkEnum: aAppendMask := mskByInteger;
            ppkDouble: aAppendMask := mskByDouble;
            ppkDate: aAppendMask := mskByDateTime;
            ppkDateTime: aAppendMask := mskByDateTime;
            ppkTime: aAppendMask := mskByDateTime;
            ppkPea:
              aAppendMask:=Format(mskByPea,[rsFirst,Pea[i].Pea.PluralCaption]);
            ppkBoolean: aAppendMask := mskByBoolean;
            Else aAppendMask := '';
          End;
          If Not(aAppendMask = '') Then
            Result += Format(aAppendMask, [Pea[i].SQLCaption]);
        End;
  End;

Begin
  aManagers := BStringsList.Build;
  aOwners := BStringsList.Build;
  For i := 0 To Pea.Properties.Count - 1 Do
    If Pea[i].Kind In [ppkPea, ppkPeas, ppkHolders] Then
      CheckBufferState(Pea[i]);

  aIndex := ClearSection(rsManagerLoadVars);
  For i := 0 To aManagers.Count - 1 Do
    AddLine(mskManagersDeclare, [aManagers[i]], 2, aIndex);
  For i := 0 To aOwners.Count - 1 Do
    AddLIne(mskOwnersListDeclare, [aOwners[i]], 2, aIndex);

  aIndex := ClearSection(rsManagerLoadPrepare);
  For i := 0 To aManagers.Count - 1 Do
    AddLine(mskBuildManagers, [aManagers[i]], 2, aIndex);
  For i := 0 To aOwners.Count - 1 Do
    AddLIne(mskBuildOwnersList, [aOwners[i]], 2, aIndex);

  aIndex := ClearSection(rsManagerLoad);
  AddLine(rsWithAQueryDo, 8, aIndex);
  Case Pea.Kind Of
    pkPlain, pkHolder:
      AddLine(mskAddObjectWithInitialize, [GetInitializeParams], 10, aIndex);
    pkTree:
      AddLine(mskAddTreeObjectWithInitialize,[GetInitializeParams], 10, aIndex);
  End;

  aIndex := ClearSection(rsManagerLoadPluralCall);
  For i := 0 To Pea.Properties.Count - 1 Do
    Case Pea[i].Kind Of
      ppkPlainPlural, ppkPeas:
        AddLine(rsLoadPluralsCall, [Pea[i].PluralCaption], 4, aIndex);
      ppkHolders:
        AddLine(rsLoadHoldersCall,
          [Pea[i].Pea.PluralCaption, Pea[i].SQLCaption], 4, aIndex);
    End;

  aIndex := ClearSection(rsManagerLoadFinal);
  For i := 0 To aOwners.Count - 1 Do
    AddLine(mskBurnOwners, [aOwners[i]], 4, aIndex);
  For i := 0 To aManagers.Count - 1 Do
    AddLine(mskBurnManagers, [aManagers[i]], 4, aIndex);
End;

Procedure BModelGeneratorClass.UpdateManagerPluralLoad;
  Function GetHolderInit(Const aPea: BPeaClass): String;
  Var
    i: Integer;
  Begin
    Result := '';
    If Not(aPea.Kind = pkHolder) Then
      Raise Exception.Create('!');
    For i := 0 To aPea.Properties.Count - 1 Do
      If Not(aPea[i].IsPlural) Then
        If aPea[i].Kind In [ppkPea] Then
          AppendCommaString(Result,
            'a%0:sManager.GetObject(aQuery.ByInteger(SQL_%s))',
            [aPea[i].Pea.PluralCaption, aPea[i].PluralCaption])
        Else
          AppendCommaString(Result, 'aQuery.%s(SQL_%s)',
            [aPea[i].KindQuery, aPea[i].SQLCaption]);
  End;
Var
  i, aIndex: Integer;
Begin
  aIndex := ClearSection(rsManagerLoadPluralDeclare);
  For i := 0 To Pea.Properties.Count - 1 Do
    If Pea[i].Kind In [ppkPlainPlural, ppkPeas] Then
      AddLine(mskManagarPluralLoadDeclare, [Pea[i].PluralCaption], 6, aIndex);

  aIndex := ClearSection(rsManagerLoadPlural);
  For i := 0 To Pea.Properties.Count - 1 Do
    If Pea[i].Kind In [ppkPlainPlural, ppkPeas] Then
      Begin
        AddLine('Procedure B%0:sManagerClass.Load%1:s(Const aQuery: BQueryClass);',
          [Pea.PluralCaption, Pea[i].PluralCaption], 0, aIndex);
        Case Pea[i].Kind Of
          ppkPeas:
            AddLines(CODE_MANAGER_PEAS_LOAD,
              [{0}Pea.Caption, {1}Pea.PluralCaption, {2}Pea[i].PluralCaption,
              {3}Pea[i].SQLCaption, {4}Pea[i].Pea.Caption,
              {5}Pea[i].Pea.PluralCaption], aIndex);
          //ppkHolders:
          //  AddLines(CODE_MANAGER_HOLDERS_LOAD,
          //    [{0}Pea.Caption, {1}Pea.PluralCaption, {2}Pea[i].PluralCaption,
          //    {3}Pea[i].SQLCaption, {4}Pea[i].Pea.HoldingPea.Caption,
          //    {5}Pea[i].Pea.HoldingPea.PluralCaption, {6}Pea[i].Pea.Caption,
          //    {7}UpCase(Pea[i].Pea.HoldingPea.Caption),
          //    {8}Pea[i].Pea.PluralCaption], aIndex);
          Else
            AddLines(CODE_MANAGER_PLAIN_LOAD,
              [Pea.Caption, Pea.PluralCaption, Pea[i].PluralCaption,
                Pea[i].SQLCaption, Pea[i].KindQuery], aIndex);
        End;
      End;
End;

Procedure BModelGeneratorClass.Update;
Begin
  UpdateUses;
  UpdateConsts;
  UpdateProperties;
  UpdateInitialize;
  UpdateInitializeObjects;
  UpdateLoadPlurals;
  UpdateAddGetRemovePlurals;
  UpdateSave;
  UpdateLoad;
  UpdateBurn;
  UpdateManagerLoad;
  UpdateManagerPluralLoad;
End;

Procedure BModelGeneratorClass.SavePeaUnit;
Begin
  bUnitFile.SaveToFile(bPeasPath + rsModelsDir +
    LowerCase(Format(mskPeaModelUnit, [Pea.Caption])));
End;

Constructor BModelGeneratorClass.Build(Const aPeaPath: String;
  Const aPea: BPeaClass; Const aProjectName: String);
Var
  aPeaModelUnit: String;
Begin
  Inherited Build(aPeaPath, aProjectName);
  bPea := aPea;

  aPeaModelUnit := bPeasPath + rsModelsDir +
    LowerCase(Format(mskPeaModelUnit, [Pea.Caption]));
  If FileExists(aPeaModelUnit) Then
    bUnitFile.LoadFromFile(aPeaModelUnit)
  Else
    InitializeUnitFile(fkModel);
End;

End.
